package cn.jcby.app.filter;

import cn.jcby.app.excpt.MSException;
import cn.jcby.app.filter.dto.LocalUserDTO;
import cn.jcby.app.util.ConstantKey;
import cn.jcby.app.util.JWTSUtils;
import cn.jcby.app.util.SpringContextUtil;
import io.jsonwebtoken.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.ArrayList;

public class JWTAuthenticationFilter extends BasicAuthenticationFilter {


    private static JWTSUtils jwtUtils;
    static {
        jwtUtils = SpringContextUtil.getBean(JWTSUtils.class);
    }

    private static final Logger logger = LoggerFactory.getLogger(JWTAuthenticationFilter.class);

    //办公SYS_0905 财务：SYS_0906
    public JWTAuthenticationFilter(AuthenticationManager authenticationManager) {
        super(authenticationManager);
    }


    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        String requestURI = request.getRequestURI();
        if (requestURI.endsWith("/login") || requestURI.endsWith("/register") || requestURI.endsWith("/getVerifyCode")) {
            UsernamePasswordAuthenticationToken authentication = getAuthentication(request, response,false);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            chain.doFilter(request, response);
            return;
        }
        String header = request.getHeader("Authorization");
        if (header == null || !header.startsWith("Bearer ")) {
            chain.doFilter(request, response);
            return;
        }
        UsernamePasswordAuthenticationToken authentication = getAuthentication(request, response,true);
        SecurityContextHolder.getContext().setAuthentication(authentication);
        chain.doFilter(request, response);

    }
    
    
    private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request, HttpServletResponse response,Boolean bool) {
        if (!bool){
            return new UsernamePasswordAuthenticationToken(null, null, new ArrayList<>());
        }
        long start = System.currentTimeMillis();
        String token = request.getHeader("Authorization");
        if (token == null || token.isEmpty()) {
            throw new MSException("Token为空");
        }
        
        String tokenStr = null;
        try {
           // Claims claims = jwtUtils.parseJwtToken(token);
            Claims claims = Jwts.parser().setSigningKey(ConstantKey.SIGNING_KEY).parseClaimsJws(token.replace("Bearer ", "")).getBody();

            long end = System.currentTimeMillis();
            logger.info("执行时间: {}", (end - start) + " 毫秒");
            tokenStr = claims.getSubject();
            logger.info("token:[" + tokenStr + "]");
            if (tokenStr != null) {                    
                String userId = tokenStr.split(ConstantKey.DELIMITER)[0];
                String mobile = tokenStr.split(ConstantKey.DELIMITER)[1];
                String inviteCode = tokenStr.split(ConstantKey.DELIMITER)[2];
                LocalUserDTO user = new LocalUserDTO() ;
                user.setUserId(userId);
                user.setMobile(mobile);
                user.setInviteCode(inviteCode);
                //添加userId、token
                return new UsernamePasswordAuthenticationToken(user, null, new ArrayList<>());
            }
        } catch (ExpiredJwtException e) {
            logger.error("Token已过期: {} " + e);
            throw new MSException("Token已过期");
        } catch (UnsupportedJwtException e) {
            logger.error("Token格式错误: {} " + e);
            throw new MSException("Token格式错误");
        } catch (MalformedJwtException e) {
            logger.error("Token没有被正确构造: {} " + e);
            throw new MSException("Token没有被正确构造");
        } catch (SignatureException e) {
            logger.error("签名失败: {} " + e);
            throw new MSException("签名失败");
        } catch (IllegalArgumentException e) {
            logger.error("非法参数异常: {} " + e);
            throw new MSException("非法参数异常");
        }
        return null;
    }
    
}
